home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / msdos / gen15khz.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  8KB  |  257 lines

  1. #include "mamalleg.h"
  2. #include "driver.h"
  3. #include <pc.h>
  4. #include <conio.h>
  5. #include <sys/farptr.h>
  6. #include <go32.h>
  7. #include <time.h>
  8. #include <math.h>
  9. #include "TwkUser.h"
  10. #include "gen15khz.h"
  11. #include "ati15khz.h"
  12.  
  13. /* from video.c */
  14. void center_mode(Register *pReg);
  15.  
  16.  
  17. int    wait_interlace;      /* config flag - indicates if we're waiting for odd/even updates */
  18. static int display_interlaced=0;  /* interlaced display */
  19.  
  20. extern int video_sync;
  21. extern int wait_vsync;
  22. extern int use_triplebuf;
  23. extern int unchained;
  24.  
  25. /* Generic SVGA 15.75KHz code and SVGA 15.75KHz driver selection */
  26.  
  27. /* To add a SVGA 15.75KHz driver for a given chipset you need to write (at least) */
  28. /* 4 functions and put them into an entry in the array below. */
  29. /* The 4 functions are as follows */
  30.  
  31. /* 1) 'Detect' -  checks for your chipset and returns 1 if found ,  0 if not */
  32.  
  33. /* 2) 'Width' - returns the logical width of the mode created */
  34. /* This is to allow for drivers (such as the generic one) which generate a mode with a very wide */
  35. /* scanline to avoid having to reprogram the card's clock */
  36.  
  37. /* 3) 'Setmode' - reprograms your chipset's clock and CRTC timing registers so that */
  38. /* it produces a signal with a horizontal scanrate of 15.75KHz and a vertical refresh rate of 60Hz. */
  39. /* (possibly producing an interlaced image if the chipset supports it) */
  40. /* NOTE: 'vdouble' is passed into the function to indicate if MAME is doubling the */
  41. /* height of the screen bitmap */
  42. /* If it is - you can set your 15.75KHz mode to drop every other scanline */
  43. /* and avoid having to interlace the display */
  44. /* (see calc_mach64_height in ati15khz.c) */
  45. /* Function should return 1 if it managed to set the 15.75KHz mode, 0 if it didn't */
  46. /* It should also call 'setinterlaceflag(<n>)'; with a value of 1 or 0 to indicate if */
  47. /* it setup an interlaced display or not. */
  48. /* This is used to determine if the refresh needs to be delayed while both odd and even fields */
  49. /* are drawn (if requested with -waitinterlace flag) */
  50.  
  51. /* 4) 'Reset' - restores any BIOS settings/tables you may have changed whilst setting up the 15.75KHz mode */
  52.  
  53. /* The Driver should : */
  54. /* .support 640x480 at 60Hz */
  55. /* .should use center_x and center_y as offsets for your horizontal and vertical retrace start/end values */
  56. /* .should use tw640x480arc_h , tw640x480arc_v for h and v timing values */
  57.  
  58. /* Sources for information about programming SVGA chipsets- */
  59. /* VGADOC4B.ZIP - from any SimTel site */
  60. /* XFree86 source code */
  61. /* the Allegro library */
  62.  
  63.  
  64.  
  65. /* our array of 15.75KHz drivers */
  66. /* NOTE: Generic *MUST* be the last in the list as its */
  67. /* detect function will always return 1 */
  68. SVGA15KHZDRIVER drivers15KHz[]=
  69. {
  70.     {"ATI", detectati, widthati15KHz, setati15KHz, resetati15KHz},   /* ATI driver */
  71.     {"Generic", genericsvga, widthgeneric15KHz, setgeneric15KHz, resetgeneric15KHz}   /* Generic driver (must be last in list) */
  72. };
  73.  
  74. /* array of CRTC settings for Generic SVGA 15.75KHz modes */
  75. /* Note - most of these values will be calculated at runtime, */
  76. /* only the H/V totals and resync starts are really important */
  77. /* 640x480 */
  78. static Register scr640x480_15KHz[] =
  79. {
  80.     { 0x3c2, 0x00, 0xe3},{ 0x3d4, 0x00, 0xc1},{ 0x3d4, 0x01, 0x9f},
  81.     { 0x3d4, 0x02, 0x9f},{ 0x3d4, 0x03, 0x91},{ 0x3d4, 0x04, 0x9f},
  82.     { 0x3d4, 0x05, 0x1f},{ 0x3d4, 0x06, 0x09},{ 0x3d4, 0x07, 0x11},
  83.     { 0x3d4, 0x08, 0x00},{ 0x3d4, 0x09, 0x40},{ 0x3d4, 0x10, 0xf2},
  84.     { 0x3d4, 0x11, 0x46},{ 0x3d4, 0x12, 0xef},{ 0x3d4, 0x13, 0x00},
  85.     { 0x3d4, 0x15, 0xef},{ 0x3d4, 0x16, 0x04}
  86. };
  87.  
  88.  
  89. /* seletct 15.75KHz driver */
  90. int getSVGA15KHzdriver(SVGA15KHZDRIVER **driver15KHz)
  91. {
  92.     int n,nodrivers;
  93. /* setup some defaults */
  94.     *driver15KHz=NULL;
  95.     display_interlaced = 0;
  96.     nodrivers = sizeof(drivers15KHz) / sizeof(SVGA15KHZDRIVER);
  97.  
  98. /* then find a driver */
  99.     for (n=0; n<nodrivers; n++)
  100.     {
  101.         if (drivers15KHz[n].detectsvgacard())
  102.         {
  103.             *driver15KHz = &drivers15KHz[n];
  104.             return 1;
  105.         }
  106.     }
  107.     return 0;
  108. }
  109.  
  110. /* generic SVGA detect, always returns true and turns off SVGA triple buffering */
  111. int genericsvga()
  112. {
  113.     use_triplebuf = 0;
  114.     return 1;
  115. }
  116.  
  117. /* generic SVGA logical width */
  118. /* to make the most compatible mode possible - */
  119. /* the generic driver's 640x480 mode is actually a 1280x240 mode that draws every other scanline */
  120. /* this means the scanrate can be lowered to arcade monitor rates without altering the card's dot clock */
  121. int widthgeneric15KHz(int width)
  122. {
  123.     return width << 1;
  124. }
  125.  
  126. /* set 15.75KHz SVGA mode using just standard VGA registers + 1 VESA function */
  127. /* may or may *NOT* work with a given chipset */
  128. int setgeneric15KHz(int vdouble, int width, int height)
  129. {
  130.     int reglen,hcount;
  131.     Register *scrSVGA_15KHz;
  132.     __dpmi_regs    _dpmi_reg;
  133. /* check the mode's supported */
  134.     if (!sup_15Khz_res(width,height))
  135.         return 0;
  136. /* now check we support the character count */
  137.  
  138.     hcount = readCRTC(HZ_DISPLAY_END);
  139.  
  140.     switch(hcount)
  141.     {
  142.         case 79:    /* 640 */
  143.             scrSVGA_15KHz = scr640x480_15KHz;
  144.             reglen = (sizeof(scr640x480_15KHz) / sizeof(Register));
  145. // set the tweak values */
  146.               scr640x480_15KHz[H_TOTAL_INDEX].value = tw640x480arc_h;
  147.             scr640x480_15KHz[V_TOTAL_INDEX].value = tw640x480arc_v;
  148.             break;
  149.         default:
  150.             logerror("15.75KHz: Unsupported %dx%d mode (%d char. clocks)\n", width, height, hcount);
  151.             return 0;
  152.     }
  153. /* setup our adjusted memory offset */
  154. /* first check if we can do it using VESA, as this gives us more flexibility than standard VGA */
  155. /* Function 6 - Get/Set Scan Line Length, VESA 1.1 and up */
  156.     _dpmi_reg.x.cx = 0;
  157.     _dpmi_reg.x.ax = 0x4F06;
  158.     _dpmi_reg.x.bx = 1;
  159.     __dpmi_int(0x10, &_dpmi_reg);
  160. /*did we get anything back ? */
  161.     if (_dpmi_reg.x.cx)
  162. /* we did, so just set the memory offset in the VGA array to whatever the mode claims to use */
  163. /* and we'll set it using VESA after the outRegArray */
  164.         scrSVGA_15KHz[MEM_OFFSET_INDEX].value = readCRTC (MEM_OFFSET);
  165.     else
  166. /* we didn't, so attempt to use the memory offset in the VGA array directly */
  167.         scrSVGA_15KHz[MEM_OFFSET_INDEX].value = (readCRTC (MEM_OFFSET) * 2);
  168.  
  169. /* indicate we're not interlacing */
  170.     setinterlaceflag (0);
  171. /* center the display */
  172.       center_mode (scrSVGA_15KHz);
  173. /* write out the array */
  174.     outRegArray (scrSVGA_15KHz,reglen);
  175.  
  176. /* did the VESA call work ?, if it did use VESA to set our memory offset */
  177.     if (_dpmi_reg.x.cx)
  178.     {
  179.         _dpmi_reg.x.ax = 0x4F06;
  180.         _dpmi_reg.x.bx = 0;
  181.         _dpmi_reg.x.cx <<= 1;
  182.         __dpmi_int(0x10, &_dpmi_reg);
  183.     }
  184.  
  185.     return 1;
  186. }
  187.  
  188. /* generic cleanup - do nothing as we only changed values in the standard VGA register set */
  189. void resetgeneric15KHz()
  190. {
  191.     return;
  192. }
  193.  
  194. /* set our interlaced flag */
  195. void setinterlaceflag(int interlaced)
  196. {
  197.     display_interlaced = interlaced;
  198.     if (display_interlaced && wait_interlace)
  199.     {
  200.         /* make sure we're going to hit around 30FPS */
  201.         video_sync = 0;
  202.         wait_vsync = 0;
  203.     }
  204. }
  205.  
  206. /* function to delay for 2 screen updates */
  207. /* allows complete odd/even field update of an interlaced display */
  208. void interlace_sync()
  209. {
  210.     /* check it's been asked for, and that the display is actually interlaced */
  211.     if (wait_interlace && display_interlaced)
  212.     {
  213.         /* make sure we get 2 vertical retraces */
  214.         vsync();
  215.         vsync();
  216.     }
  217. }
  218.  
  219.  
  220. /* read a CRTC register at a given index */
  221. int readCRTC(int nIndex)
  222. {
  223.     outportb (0x3d4, nIndex);
  224.     return inportb (0x3d5);
  225. }
  226.  
  227. /* Get vertical display height */
  228. /* -it's stored over 3 registers */
  229. int getVtEndDisplay()
  230. {
  231.     int   nVert;
  232. /* get first 8 bits */
  233.     nVert = readCRTC (VT_DISPLAY_END);
  234. /* get 9th bit */
  235.     nVert |= (readCRTC (CRTC_OVERFLOW) & 0x02) << 7;
  236. /* and the 10th */
  237.     nVert |= (readCRTC (CRTC_OVERFLOW) & 0x40) << 3;
  238.     return nVert;
  239. }
  240.  
  241.  
  242. int sup_15Khz_res(int width,int height)
  243. {
  244. /* 640x480 */
  245.     if (width == 640 && height == 480)
  246.         return 1;
  247. /* 800x600 */
  248. /*
  249.     if(width==800&&height==600)
  250.         return 1;
  251. */
  252.     logerror("15.75KHz: Unsupported %dx%d mode\n", width, height);
  253.     return 0;
  254. }
  255.  
  256.  
  257.